package top.lixunda.commerce.common.core.controller.wrapper;

import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * @author LiXunda
 * @version time:2019/10/14 9:49
 */
@Slf4j
public abstract class AbstractSqlWrapper<T> implements IAbstractSqlWrapper<T> {

    private ConditionBlock conditionBlock = ConditionBlock.andSqlBlock();

    private ConditionBlock now = conditionBlock;

    private OtherBlock otherBlock = new OtherBlock();

    @Override
    public ConditionBlock getConditionBlock() {
        return conditionBlock;
    }

    @Override
    public void setConditionBlock(ConditionBlock conditionBlock) {
        this.conditionBlock = conditionBlock;
    }

    @Override
    public ConditionBlock getNow() {
        return now;
    }

    @Override
    public void setNow(ConditionBlock now) {
        this.now = now;
    }

    @Override
    public OtherBlock getOtherBlock() {
        return otherBlock;
    }

    @Override
    public void setOtherBlock(OtherBlock otherBlock) {
        this.otherBlock = otherBlock;
    }

    @Override
    public IAbstractSqlWrapper<T> groupBy(String... column) {
        this.otherBlock.groupBy(column);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> orderBy(Map<String, String> map) {
        this.otherBlock.orderBy(map);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> orderBy(String column, String value) {
        this.otherBlock.orderBy(column, value);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> orderByAsc(String... columns) {
        for (String column : columns) {
            orderBy(column, OtherBlock.ORDER_BY_ASC);
        }
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> orderByDesc(String... columns) {
        for (String column : columns) {
            orderBy(column, OtherBlock.ORDER_BY_DESC);
        }
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> having(String column) {
        this.otherBlock.having(column);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> limit(int start, int count) {
        this.otherBlock.page(start, count);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> allEq(Map<String, Object> map) {
        Map<String, String> newMap = new HashMap<>(16);
        if (map != null) {
            map.forEach((key, value) -> newMap.put(key, String.valueOf(value)));
        }
        this.now = this.now.allEq(newMap);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> eq(String column, Object value) {
        this.now = this.now.eq(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> ne(String column, Object value) {
        this.now = this.now.ne(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> gt(String column, Object value) {
        this.now = this.now.gt(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> ge(String column, Object value) {
        this.now = this.now.ge(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> lt(String column, Object value) {
        this.now = this.now.lt(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> le(String column, Object value) {
        this.now = this.now.le(column, String.valueOf(value));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> between(String column, Object value1, Object value2) {
        this.now = this.now.between(column, String.valueOf(value1), String.valueOf(value2));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> notBetween(String column, Object value1, Object value2) {
        this.now = this.now.notBetween(column, String.valueOf(value1), String.valueOf(value2));
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> like(String column, String value) {
        this.now = this.now.like(column, value);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> notLike(String column, String value) {
        this.now = this.now.notLike(column, value);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> likeLeft(String column, String value) {
        this.now = this.now.likeLeft(column, value);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> likeRight(String column, String value) {
        this.now = this.now.likeRight(column, value);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> isNull(String... column) {
        this.now = this.now.isNull(column);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> isNotNull(String... column) {
        this.now = this.now.isNotNull(column);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> in(String column, List<?> values) {
        List<String> newList = new ArrayList<>();
        if (values != null) {
            values.forEach(item -> newList.add(String.valueOf(item)));
        }
        this.now = this.now.in(column, newList);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> notIn(String column, List<?> values) {
        List<String> newList = new ArrayList<>();
        if (values != null) {
            values.forEach(item -> newList.add(String.valueOf(item)));
        }
        this.now = this.now.notIn(column, newList);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> apply(String applySql, Object... params) {
        List<String> newList = new ArrayList<>();
        if (params != null) {
            Arrays.asList(params).forEach(item -> newList.add(String.valueOf(item)));
        }
        this.now = this.now.apply(applySql, newList);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> or() {
        this.now = this.now.or();
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> and() {
        this.now = this.now.and();
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> or(ConditionBlock sqlBlock) {
        this.now = this.now.or(sqlBlock);
        return this;
    }

    @Override
    public IAbstractSqlWrapper<T> and(ConditionBlock sqlBlock) {
        this.now = this.now.and(sqlBlock);
        return this;
    }

    @Override
    public abstract EntityBlock<T> getEntityBlock();

    @Override
    public T getEntity() {
        return getEntityBlock().getEntity();
    }

    @Override
    public IAbstractSqlWrapper<T> setEntity(T t) {
        getEntityBlock().setEntity(t);
        return this;
    }
}
